/*
   Copyright (c) 2019 Shanghai Xuanzi Technology Co. Ltd https://xuanzi.ltd
   XZMindMap is licensed under the Mulan PSL v1.
   You can use this software according to the terms and conditions of the Mulan PSL v1.
   You may obtain a copy of Mulan PSL v1 at:
      http://license.coscl.org.cn/MulanPSL
   THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
   IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
   PURPOSE.
   See the Mulan PSL v1 for more details.

*/

package xuanzi.commons.graphics;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Path  {
  
	public List<Shape> shapes = new ArrayList<Shape>();
	
	static Map<String,Path> pathBuffer = new HashMap<String, Path>();

	public static boolean debug = true;
	
	
	public Path() {
	 
	}
	
	public Path(String paths) {
		parsePath(paths,-1);
	}
	
	public Path(String paths,float size) {
		parsePath(paths,size);
	}
	
	public static Path fromIcon(String name,float size) { 
		String key = name+size;
		Path path = pathBuffer.get(key);
		if(path==null) {
			String paths = getIcon(name.replace("icon://", "").replace(".icon/", "")); 
			path = new Path(paths,size);
			pathBuffer.put(key, path);
		}
		return path;
	}
	
	public static Path fromIcon(String name) { 
		String paths = getIcon(name.replace("icon://", "").replace(".icon/", "")); 
		return new Path(paths);
	}
	
	public static  String getIcon(String name){
		if(debug) {
			return "S1792 1792M320 1280Q320 1208 256 1170L256 -96Q256 -109 246.50 -118.50Q237 -128 224 -128L160 -128Q147 -128 137.50 -118.50Q128 -109 128 -96L128 1170Q64 1208 64 1280Q64 1333 101.50 1370.50Q139 1408 192 1408Q245 1408 282.50 1370.50Q320 1333 320 1280M1792 1216L1792 453Q1792 428 1779.50 414.50Q1767 401 1740 387Q1525 271 1371 271Q1310 271 1247.50 293Q1185 315 1139 341Q1093 367 1023.50 389Q954 411 881 411Q689 411 417 265Q400 256 384 256Q358 256 339 275Q320 294 320 320L320 1062Q320 1094 351 1117Q372 1131 430 1160Q666 1280 851 1280Q958 1280 1051 1251Q1144 1222 1270 1163Q1308 1144 1358 1144Q1412 1144 1475.50 1165Q1539 1186 1585.50 1212Q1632 1238 1673.50 1259Q1715 1280 1728 1280Q1754 1280 1773 1261Q1792 1242 1792 1216Z";
		}
		return getIconFromResource(name);
	}
	
	public static native String getIconFromResource(String name)/*-{
		console.log(name+"get");
		if(!require){
			return "";
		}
		var icons = require("icons.js");
		return icons.icon(name);
	}-*/; 
	
	float scale = 0.1f,tx,ty;


	private void parsePath(String paths,float size) { 
		StringBuilder buffer = new StringBuilder();
		String param; 
		char op ='M';
		for(int i=0;i<paths.length();i++) {
			char c = paths.charAt(i);
			if(c=='M'||c=='L'||c=='Q'||c=='S') { 
				param = buffer.toString();
				if(param.length()>0) {
					doOp(op,param.trim(),size);
				}
				op = c;
				buffer.delete(0, buffer.length());
			}else if(c=='Z') {
				close();
			}else
				buffer.append(c); 
		}
		
	}

	private float[] pointValue(String attrs) {
		String[] sp = attrs.split(" ");
		float[] values = new float[2]; 
		for(int i=0;i<sp.length;i++) {
			values[i] = Float.parseFloat(sp[i]);
		} 
		return values;
	}
	
 
	private void doOp(char c,String param,float size) { 
		
		if(c=='M') { 
			float[] values = pointValue(param); 
			 moveTo((values[0]+tx)*scale, -(values[1]+ty)*scale);
		}else  if(c=='L'){
			float[] values = pointValue(param); 
			lineTo((values[0]+tx)*scale, -(values[1]+ty)*scale); 
		}else  if(c=='Q'){
			String[] s = param.split("[ ]");
			quadTo(
					(Float.parseFloat(s[0])+tx)*scale, -(Float.parseFloat(s[1])+ty)*scale,
					(Float.parseFloat(s[2])+tx)*scale, -(Float.parseFloat(s[3])+ty)*scale
			);
		}else  if(c=='S'){
			float[] values = pointValue(param); 
			maxWidth = values[0];
			maxHeight = values[1];
			ty = -maxHeight * 0.3f;
			tx = -maxWidth * 0.5f;
			scale = size / maxHeight;
		}
	}
	
	float maxWidth,maxHeight;

	public void close() {
		Close c = new Close();
		shapes.add(c);
	}

	public void cubicTo(float x1, float y1, float x2, float y2, float x3, float y3) { 
		CubicTo ct = new CubicTo(x1, y1, x2, y2, x3, y3);
		shapes.add(ct);
	}

	public void moveTo(float x, float y) {
		MoveTo mt = new MoveTo(x, y);
		shapes.add(mt);
	}

	public void lineTo(float x, float y){
		LineTo lt = new LineTo(x, y);
		shapes.add(lt);
	}

	public void quadTo(float x, float y, float x2, float y2){
		QuadTo qt = new QuadTo(x, y, x2, y2);
		shapes.add(qt);
	}
	


	public void reset(){
		shapes.clear();
		//Reset reset = new Reset();
		//shapes.add(reset);
	}
	
	public static interface Shape{
		
	}
	
	public static class Reset implements Shape{
		  
		
	}
	
	public static class MoveTo implements Shape{
		
		public float x,y;
		
		public MoveTo(float x,float y){
			this.x = x;
			this.y = y;
		}

		
	}
	
	public static class LineTo implements Shape{
		
		public float x,y;
		
		public LineTo(float x,float y){
			this.x = x;
			this.y = y;
		}

		
	}
	
	public static class QuadTo implements Shape{
		
		public float x1,y1,x2,y2;
		
		public QuadTo(float x,float y,float x2,float y2){
			this.x1 = x;
			this.y1 = y;
			this.x2 = x2;
			this.y2 = y2;
		}
 
		
	}
	
	public static class OVal implements Shape{
		
		public BoxF rect;
		
		public OVal(BoxF rect){
			this.rect = rect;
		}
 
		
	}
	
	public static class Round implements Shape{
		
		public BoxF rect;
		
		float rx,ry;
		
		public Round(BoxF rect,float rx,float ry){
			this.rect = rect;
			this.rx = rx;
			this.ry = ry;
		}

		
	}
	

	public static class Box implements Shape{
		
		public BoxF rect;
		
		public Box(BoxF rect){
			this.rect = rect;
		}

		
		
	}
	
	public static class Close implements Shape{
		  
	}
	
	public static class CubicTo implements Shape{
		
		public float x1,y1,x2,y2,x3,y3;
		
		public CubicTo(float x,float y,float x2,float y2,float x3,float y3){
			this.x1 = x;
			this.y1 = y;
			this.x2 = x2;
			this.y2 = y2;
			this.x3 = x3;
			this.y3 = y3;
		}

	}
	
 
}
